import CesiumNavigation from 'cesium-navigation-es6'
import axios from 'axios'
let cesiumInit = {
  init(el) {
    this.initViewer(el) // 初始化cesium
  },
  //初始化viewer
  initViewer(el) {
    //Cesium官网注册后的授权token，没有token不能使用cesium在线的地形服务，这里需要改成自己的token
    Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI5NjE1MDIwOC1jOGYxLTQzZWItYjNhOC1iNjZlMWM1OGYxMDIiLCJpZCI6MTAyODY5LCJpYXQiOjE2NTkwMDA3ODN9.Vy4hW4jpjbZs6ee4BcRl3-cCl-oRGn42e2_Hjbo5nas'
    this.viewer = new Cesium.Viewer(el, {
      animation: false, // 是否显示动画控件
      baseLayerPicker: false, // 是否显示图层选择控件
      vrButton: false, // 是否显示VR控件
      geocoder: false, // 是否显示地名查找控件
      timeline: true, // 是否显示时间线控件
      sceneModePicker: false, // 是否显示投影方式控件
      navigationHelpButton: false, // 是否显示帮助信息控件
      navigationInstructionsInitiallyVisible: false, // 帮助按钮，初始化的时候是否展开
      infoBox: false, // 是否显示点击要素之后显示的信息
      fullscreenButton: false, // 是否显示全屏按钮
      selectionIndicator: false, // 是否显示选中指示框
      homeButton: false, // 是否显示返回主视角控件
      scene3DOnly: false, // 如果设置为true，则所有几何图形以3D模式绘制以节约GPU资源
      terrainProvider: new Cesium.EllipsoidTerrainProvider({}) // 不显示地形
      // terrainProvider: new Cesium.CesiumTerrainProvider({
      //   url: Cesium.IonResource.fromAssetId(1),
      //   requestWaterMask: true, // 请求水体效果所需要的海岸线数据
      //   requestVertexNormals: true, // 请求地形照明数据
      // }), // 不显示地形
    })

    // 是否支持图像渲染像素化处理，在支持image-rendering: pixelated属性的浏览器中，根据设备像素比例来设置 Cesium 场景的分辨率缩放，以达到更好的视觉效果。
    if (Cesium.FeatureDetection.supportsImageRenderingPixelated()) {
      this.viewer.resolutionScale = window.devicePixelRatio
    }

    // 开启抗锯齿
    this.viewer.scene.postProcessStages.fxaa.enabled = true
    this.viewer.scene.postProcessStages.fxaa.pixelRatio = 0.5 // 像素比例，可根据需要进行调整
    this.viewer._cesiumWidget._creditContainer.style.display = 'none'
    this.viewer.scene.globe.depthTestAgainstTerrain = true
    // this.viewer.scene.globe.enableLighting = false; // 开启光照

    this.viewer.scene.light = new Cesium.DirectionalLight({
      direction: new Cesium.Cartesian3(0.354925, -0.890918, -0.1)
    })

    this.viewer.timeline.makeLabel = function (date, viewerModel) {
      const julianDT = new Cesium.JulianDate()
      Cesium.JulianDate.addHours(date, 8, julianDT)
      var gregorianDT = Cesium.JulianDate.toGregorianDate(julianDT)

      let hour = gregorianDT.hour + ''
      let minute = gregorianDT.minute + ''
      let second = gregorianDT.second + ''
      return `${gregorianDT.year}年${gregorianDT.month}月${gregorianDT.day}日${hour.padStart(2, '0')}:${minute.padStart(2, '0')}:${second.padStart(2, '0')}`
    }
    this.cesiumNavigation = new CesiumNavigation(this.viewer, {
      enableCompass: true, //指南针
      enableZoomControls: true, //是否启用缩放控件
      enableDistanceLegend: true //比例尺
    })
    this.viewer.timeline.container.style.display = 'none'

    // 将原来鼠标左键拖动平移视图修改为鼠标右键拖动
    this.viewer.scene.screenSpaceCameraController.rotateEventTypes = [Cesium.CameraEventType.LEFT_DRAG]
    // 将原来鼠标中键倾斜视图修改为鼠标左键拖动
    this.viewer.scene.screenSpaceCameraController.tiltEventTypes = [Cesium.CameraEventType.RIGHT_DRAG]
    // 将原来鼠标右键拖动缩放修改为鼠标滚轮滚动
    this.viewer.scene.screenSpaceCameraController.zoomEventTypes = [Cesium.CameraEventType.WHEEL]
    // 最小缩放高度（米）
    this.viewer.scene.screenSpaceCameraController.minimumZoomDistance = 30
    // 最大缩放高度（米）
    this.viewer.scene.screenSpaceCameraController.maximumZoomDistance = 1500
    window.viewer = this.viewer
    // console.log('创建成功 Viewer',window.viewer,);
    
  },
  backViewer() {
    return this.viewer
  },
  // 加载3d
  async load3ditles() {
    const {data} = await axios.get('./config/cesium/tiles.json')
    let tilesetJson = {
      url: `${data.tiles}/tileset.json`,
      // modelMatrix: Cesium.Matrix4.fromArray([0.99728705282568, -0.07133690478857654, 0.018154346076228484, 0, 0.07196348774962635, 0.9967360428469336, -0.03658575297495703, 0, -0.015485176691900499, 0.03779294782126241, 0.9991656030897983, 0, -150.54712372994982, 367.4236145177856, 786.9828416663222, 1]),
      // show: true, // 是否显示图块集(默认true)
      skipLevelOfDetail: true, // --- 优化选项。确定是否应在遍历期间应用详细级别跳过(默认false)
      baseScreenSpaceError: 1024, // --- When skipLevelOfDetailis true，在跳过详细级别之前必须达到的屏幕空间错误(默认1024)
      maximumScreenSpaceError: 1, // 数值加大，能让最终成像变模糊---用于驱动细节细化级别的最大屏幕空间误差(默认16)原128
      skipScreenSpaceErrorFactor: 2, // --- 何时skipLevelOfDetail是true，定义要跳过的最小屏幕空间错误的乘数。与 一起使用skipLevels来确定要加载哪些图块(默认16)
      skipLevels: 1, // --- WhenskipLevelOfDetail是true一个常量，定义了加载图块时要跳过的最小级别数。为 0 时，不跳过任何级别。与 一起使用skipScreenSpaceErrorFactor来确定要加载哪些图块。(默认1)
      immediatelyLoadDesiredLevelOfDetail: false, // --- 当skipLevelOfDetail是时true，只会下载满足最大屏幕空间错误的图块。忽略跳过因素，只加载所需的图块(默认false)
      loadSiblings: false, // 如果为true则不会在已加载完概况房屋后，自动从中心开始超清化房屋 --- 何时确定在遍历期间skipLevelOfDetail是否true始终下载可见瓦片的兄弟姐妹(默认false)
      cullWithChildrenBounds: false, // ---优化选项。是否使用子边界体积的并集来剔除瓦片（默认true）
      cullRequestsWhileMoving: false, // ---优化选项。不要请求由于相机移动而在返回时可能未使用的图块。这种优化只适用于静止的瓦片集(默认true)
      cullRequestsWhileMovingMultiplier: 10, // 值越小能够更快的剔除 ---优化选项。移动时用于剔除请求的乘数。较大的是更积极的剔除，较小的较不积极的剔除(默认60)原10
      preloadWhenHidden: true, // ---this.tileset.show时 预加载瓷砖false。加载图块，就好像图块集可见但不渲染它们(默认false)
      preloadFlightDestinations: true, // ---优化选项。在相机飞行时在相机的飞行目的地预加载图块(默认true)
      preferLeaves: true, // ---优化选项。最好先装载叶子(默认false)
      maximumMemoryUsage: 2048, // 内存分配变小有利于倾斜摄影数据回收，提升性能体验---瓦片集可以使用的最大内存量（以 MB 为单位）(默认512)原512 4096
      progressiveResolutionHeightFraction: 0.5, // 数值偏于0能够让初始加载变得模糊 --- 这有助于在继续加载全分辨率图块的同时快速放下图块层(默认0.3)
      dynamicScreenSpaceErrorDensity: 10, // 数值加大，能让周边加载变快 --- 用于调整动态屏幕空间误差的密度，类似于雾密度(默认0.00278)
      dynamicScreenSpaceErrorFactor: 1, // 不知道起了什么作用没，反正放着吧先 --- 用于增加计算的动态屏幕空间误差的因素(默认4.0)
      dynamicScreenSpaceErrorHeightFalloff: 0.25, // --- 密度开始下降的瓦片集高度的比率(默认0.25)
      foveatedScreenSpaceError: true, // --- 优化选项。通过暂时提高屏幕边缘周围图块的屏幕空间错误，优先加载屏幕中心的图块。一旦Cesium3DTileset#foveatedConeSize加载确定的屏幕中心的所有图块，屏幕空间错误就会恢复正常。(默认true)
      foveatedConeSize: 0.1, // --- 优化选项。当Cesium3DTileset#foveatedScreenSpaceError为 true 时使用来控制决定延迟哪些图块的锥体大小。立即加载此圆锥内的瓷砖。圆锥外的瓷砖可能会根据它们在圆锥外的距离及其屏幕空间误差而延迟。这是由Cesium3DTileset#foveatedInterpolationCallback和控制的Cesium3DTileset#foveatedMinimumScreenSpaceErrorRelaxation。将此设置为 0.0 意味着圆锥将是由相机位置及其视图方向形成的线。将此设置为 1.0 意味着锥体包含相机的整个视野,禁用效果(默认0.1)
      foveatedMinimumScreenSpaceErrorRelaxation: 0.0, // --- 优化选项。当Cesium3DTileset#foveatedScreenSpaceError为 true 时使用以控制中央凹锥之外的图块的起始屏幕空间误差松弛。屏幕空间错误将从 this.tileset 值开始Cesium3DTileset#maximumScreenSpaceError根据提供的Cesium3DTileset#foveatedInterpolationCallback.(默认0.0)
      // foveatedTimeDelay: 0.2, // ---优化选项。使用 whenCesium3DTileset#foveatedScreenSpaceError为 true 来控制在相机停止移动后延迟瓷砖开始加载之前等待的时间（以秒为单位）。此时间延迟可防止在相机移动时请求屏幕边缘周围的瓷砖。将此设置为 0.0 将立即请求任何给定视图中的所有图块。(默认0.2)
      luminanceAtZenith: 0.2, // --- 用于此模型的程序环境贴图的天顶处的太阳亮度（以千坎德拉每平方米为单位）(默认0.2)
      backFaceCulling: true, // --- 是否剔除背面几何体。当为 true 时，背面剔除由 glTF 材质的 doubleSided 属性确定；如果为 false，则禁用背面剔除(默认true)
      debugFreezeFrame: false, // --- 仅用于调试。确定是否应仅使用最后一帧的图块进行渲染(默认false)
      debugColorizeTiles: false, // --- 仅用于调试。如果为 true，则为每个图块分配随机颜色(默认false)
      debugWireframe: false, // --- 仅用于调试。如果为 true，则将每个图块的内容渲染为线框(默认false)
      debugShowBoundingVolume: false, // --- 仅用于调试。如果为 true，则为每个图块渲染边界体积(默认false)
      debugShowContentBoundingVolume: false, // --- 仅用于调试。如果为 true，则为每个图块的内容渲染边界体积(默认false)
      debugShowViewerRequestVolume: false, // --- 仅用于调试。如果为 true，则呈现每个图块的查看器请求量(默认false)
      debugShowGeometricError: false, // --- 仅用于调试。如果为 true，则绘制标签以指示每个图块的几何误差(默认false)
      debugShowRenderingStatistics: false, // --- 仅用于调试。如果为 true，则绘制标签以指示每个图块的命令、点、三角形和特征的数量(默认false)
      debugShowMemoryUsage: false, // --- 仅用于调试。如果为 true，则绘制标签以指示每个图块使用的纹理和几何内存（以兆字节为单位）(默认false)
      debugShowUrl: false, // --- 仅用于调试。如果为 true，则绘制标签以指示每个图块的 url(默认false)
      dynamicScreenSpaceError: true // 根据测试，有了这个后，会在真正的全屏加载完之后才清晰化房屋 --- 优化选项。减少距离相机较远的图块的屏幕空间错误(默认false)
    }
    this.tileset = new Cesium.Cesium3DTileset(tilesetJson)

    this.tileset.readyPromise.then(() => {
      this.viewer.scene.primitives.add(this.tileset)

      var heightOffset = 0 // 模型相对于地面的高度偏移量
      var cartographic = Cesium.Cartographic.fromCartesian(this.tileset.boundingSphere.center)
      var surfacePosition = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0)
      var offsetPosition = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, heightOffset)
      var translation = Cesium.Cartesian3.subtract(offsetPosition, surfacePosition, new Cesium.Cartesian3())

      var modelMatrix = Cesium.Matrix4.fromTranslation(translation)
      this.tileset.modelMatrix = modelMatrix
      // let boundingSphere = this.tileset.boundingSphere;
      // 获取模型的中心点坐标
      // const center = boundingSphere.center;
      // console.log(center, '获取模型的中心点坐标');
      // 将模型中心点坐标转换为经纬度
    })
    // 设置偏移量
    this.tileset.allTilesLoaded.addEventListener(() => {
      // console.log('模型已经全部加载完成')
    })
  },
  backTileset() {
    return this.tileset
  },
  // 坐标获取
  handleMouseClick(callback) {
    let handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas)
    handler.setInputAction((movement) => {
      let cartesian = this.viewer.camera.pickEllipsoid(movement.position, this.viewer.scene.globe.ellipsoid)
      // console.log('空间坐标', cartesian)
      if (cartesian == undefined) {
        callback('No')
      } else {
        let cartographic = Cesium.Cartographic.fromCartesian(cartesian)
        let lon = Cesium.Math.toDegrees(cartographic.longitude)
        let lat = Cesium.Math.toDegrees(cartographic.latitude)
        //   console.log('经纬度是：', { x: lon, y: lat })
        let pickedObject = this.viewer.scene.pick(movement.position)
        // console.log(pickedObject, 'pickedObject')
        callback({cartesian, lon, lat, pickedObject})
      }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
  },
  destroy() {
    this.viewer.entities.removeAll()
    this.viewer.imageryLayers.removeAll(true)
    this.viewer.destroy()
    // console.log('销毁了实体、图像图层，Viewer对象的操作')
  }
}
export default cesiumInit
